<?php

namespace C\S\Item;

use C\M\ItemAprList as ItemAprListModel;
use C\L\Service;
use Phalcon\Mvc\Model\Resultset\Simple as Resultset;

class ItemAprList extends Service
{
    protected function setModel()
    {
        $this->model = new \C\M\ItemAprList();
    }

    public function getStatusConfig()
    {
        return [
            'status' => [
                'D' => '未发放',
                'Y' => '已发放',
            ],
        ];
    }

    public function successBackList($id)
    {
        $list = $this->di['s_itemaprlist']->searchAll(['cid'=>$id], [], [], 'back_time desc');

        $status = ['D' => '未发放','Y' => '已发放'];
        $ben = [];
        foreach ($list as &$v) {
            $v['status_name'] = $status[$v['status']];
            $v['back_time_date'] = ($v['back_time'])?date('Y/m/d', $v['back_time']): '';
            $v['ok_time_date'] = ($v['ok_time'])?date('Y/m/d', $v['ok_time']): '';
            $v['type'] = 2;
            if ($v['money'] > 0) {
                $ben = $v;
            }
        }
        if (!empty($ben)) {
            $ben['type'] = 1;
            array_unshift($list, $ben);
        }
        
        return $list;
    }

    public function moneyBackList($id)
    {
        $list = $this->di['s_itemaprlist']->search(
            [
                'cid'   => $id,
                'money' => 0,
            ],
            [
                'money'=>'>=',
            ]
        );

        $status = $this->getStatusConfig();

        if ($list) {
            $list['type'] = 1;
            $list['status_name'] = $status['status'][$list['status']];
        }

        return $list;
    }

    public function getProfitFromOrder($order)
    {
        $commissions = $this->getCommissionFromOrder($order);
        return array_reduce($commissions, function ($result, $item) {
            $result = bcadd($result, $item['apr_money'], 2);
            return $result;
        }, 0);
    }

    public function getCommissionFromOrder($order)
    {
        [
            'commission' => $commission,
        ] = json_decode($order->other_info, true);

        $rate = $commission['rate'];
        if ($commission['vip_bonus'] == 'enabled') {
            $rate = bcadd($rate, $commission['vip_rate'], 2);
        }

        return $this->getCommission(
            $commission['type'],
            $order->user_id,
            $order->id,
            $order->amount,
            $rate,
            $commission['period'],
        );
    }

    public function getCommission(
        $type,
        $userId,
        $cid,
        $amount,
        $rate,
        $period
    ) {
        $methodName = 'dispatchCommissionType'.$type;

        return $this->$methodName($userId, $cid, $amount, $rate, $period);
    }


    public function dispatchCommissionFromOrder($order)
    {
        [
            'commission' => $commission,
        ] = json_decode($order->other_info, true);

        $rate = $commission['rate'];
        if ($commission['vip_bonus'] == 'enabled') {
            $rate = bcadd($rate, $commission['vip_rate'], 2);
        }

        return $this->dispatchCommission(
            $commission['type'],
            $order->user_id,
            $order->id,
            $order->amount,
            $rate,
            $commission['period'],
        );
    }

    public function dispatchCommission(
        $type,
        $userId,
        $cid,
        $amount,
        $rate,
        $period
    ) {
        $methodName = 'dispatchCommissionType'.$type;

        $commissions = $this->$methodName($userId, $cid, $amount, $rate, $period);

        return $this->saves($commissions);
    }

    private function dispatchCommissionTypeA(
        $userId,
        $cid,
        $amount,
        $rate,
        $period
    ) {
        $now = time();
        return array_map(function ($item) use ($userId, $cid, $amount, $rate, $period, $now) {
            return [
                'cid'       => $cid,
                'uid'       => $userId,
                'money'     => $item == $period ? $amount : 0,
                'apr_money' => bcmul($rate / 100, $amount, 2),
                'back_time' => $now + $item * 24 * 3600,
            ];
        }, range(1, $period));
    }

    private function dispatchCommissionTypeB(
        $userId,
        $cid,
        $amount,
        $rate,
        $period
    ) {
        $total = $amount * ($rate / 100 + 1) ** $period;
        return [[
            'cid'       => $cid,
            'uid'       => $userId,
            'money'     => $amount,
            'apr_money' => bcsub($total, $amount, 2),
            'back_time' => time() + $period * 24 * 3600,
        ]];
    }
    private function dispatchCommissionTypeC(
        $userId,
        $cid,
        $amount,
        $rate,
        $period
    ) {
        return [[
            'cid'       => $cid,
            'uid'       => $userId,
            'money'     => $amount,
            'apr_money' => bcmul($rate / 100 * $amount, $period, 2),
            'back_time' => time() + $period * 24 * 3600,
        ]];
    }

    // 获取分佣列表
    public function getAprListAction($currentPage, $perPage, $params)
    {
        $cloumn = " commission.*, user.name, user.mobile, group_buying_order.sn as order_sn";
        $sql_base = "
            SELECT {cloumn} FROM
                (
                    SELECT id, cid, uid, money as amount, status, back_time, ok_time, \"money\" as type FROM item_apr_list WHERE money > 0
                    UNION ALL
                    SELECT id, cid, uid, apr_money as amount, status, back_time, ok_time, \"commission\" as type FROM item_apr_list WHERE apr_money > 0
                ) as commission
            LEFT JOIN user ON commission.uid = user.uid
            LEFT JOIN group_buying_order ON commission.cid = group_buying_order.id
";

        $sql = str_replace("{cloumn}", $cloumn, $sql_base);
        $sql .= $this->createSqlConditions($params);

        $first_num = ($currentPage - 1) * $perPage;
        $last_num = $first_num + $perPage - 1;
        $sql .= " ORDER BY commission.id DESC, FIELD(commission.type, 'money', 'commission') LIMIT $first_num, $last_num";

        $ItemAprList = new \C\M\ItemAprList();

        $queryResult = new Resultset(
            null,
            $ItemAprList,
            $ItemAprList->getReadConnection()->query($sql)
        );
        $item = $queryResult->toArray();

        $count = $this->getAprListCount($sql_base, $params);
        $result = [
            'items' => $item,
            'pagination' => $this->getPagination($currentPage, $perPage, $count)
        ];
        return $result;
    }

    // 拼接sql语句的条件
    private function createSqlConditions($params)
    {
        $conditions = " WHERE 1 = 1";
        if (isset($params['user_id'])) {
            $uid = $params['user_id'];
            $conditions .= " AND commission.uid = $uid";
        }

        if (isset($params['type'])) {
            $type = $params['type'];
            $conditions .= " AND commission.type = '$type'";
        }

        if (isset($params['status'])) {
            $status = $params['status'];
            $conditions .= " AND commission.status = '$status'";
        }

        if (isset($params['start_date']) && isset($params['end_date'])) {
            $start_date = $params['start_date'];
            $end_date = $params['end_date'];
            $conditions .= " AND commission.back_time >= $start_date AND commission.back_time <= $end_date";
        }
        return $conditions;
    }

    //获取列表总条数
    private function getAprListCount($sql_base, $params)
    {
        $cloumn = " count(*) as count ";
        $sql = str_replace("{cloumn}", $cloumn, $sql_base);
        $sql .= $this->createSqlConditions($params);

        $ItemAprList = new \C\M\ItemAprList();
        $queryResult = new Resultset(
            null,
            $ItemAprList,
            $ItemAprList->getReadConnection()->query($sql)
        );
        $count = $queryResult->toArray()[0]['count'];
        return $count;
    }

    //获取列表分页参数
    private function getPagination($currentPage, $perPage, $count)
    {
        $pagination = [
            'total'        => (int) $count,
            'per_page'     => (int) $perPage,
            'total_page'   => (int) ceil($count / $perPage),
            'current_page' => (int) $currentPage,
        ];

        return $pagination;
    }

    public function dispatchByCids($cids)
    {
        $conditions = "status = 'D' AND cid IN ({cids:array})";
        $bind = [ 'cids' => $cids ];
        $commissions = ItemAprListModel::find(compact('conditions', 'bind'));

        try {
            $this->di['db']->begin();
            foreach ($commissions as $commission) {
                $updateResult = $this->update(
                    $commission->id,
                    ['status' => 'Y', 'ok_time' => time()]
                );
                if (!$updateResult) {
                    throw new \Exception('更新佣金信息失败');
                }

                $addCommissionFundsResult = $this->di['s_funds']->add(
                    $commission->uid,
                    $commission->apr_money,
                    'money',
                    'item_apr_money',
                    "订单盈利",
                    $commission->id,
                );
                if (!$addCommissionFundsResult) {
                    throw new \Exception('添加分佣记录失败');
                }

                if ($commission->money > 0) {
                    $addMoneyFundsResult = $this->di['s_funds']->add(
                        $commission->uid,
                        $commission->money,
                        'money',
                        'item_back_money',
                        "订单本金",
                        $commission->id,
                    );
                    if (!$addMoneyFundsResult) {
                        throw new \Exception('添加本金记录失败');
                    }
                }
            }

            $this->di['db']->commit();
        } catch (\Exception $error) {
            if ($this->di['db']->isUnderTransaction()) {
                $this->di['db']->rollback();
            }

            return false;
        }

        return true;
    }

    public function dispatchAll()
    {
        $conditions = "status = 'D'";
        $commissions = ItemAprListModel::find(compact('conditions'));

        try {
            $this->di['db']->begin();
            foreach ($commissions as $commission) {
                $updateResult = $this->update(
                    $commission->id,
                    ['status' => 'Y', 'ok_time' => time()]
                );
                if (!$updateResult) {
                    throw new \Exception('更新佣金信息失败');
                }

                $addCommissionFundsResult = $this->di['s_funds']->add(
                    $commission->uid,
                    $commission->apr_money,
                    'money',
                    'item_apr_money',
                    "订单盈利",
                    $commission->id,
                );
                if (!$addCommissionFundsResult) {
                    throw new \Exception('添加分佣记录失败');
                }

                if ($commission->money > 0) {
                    $addMoneyFundsResult = $this->di['s_funds']->add(
                        $commission->uid,
                        $commission->money,
                        'money',
                        'item_back_money',
                        "订单本金",
                        $commission->id,
                    );
                    if (!$addMoneyFundsResult) {
                        throw new \Exception('添加本金记录失败');
                    }
                }
            }

            $this->di['db']->commit();
        } catch (\Exception $error) {
            if ($this->di['db']->isUnderTransaction()) {
                $this->di['db']->rollback();
            }

            return false;
        }

        return true;
    }
}
